home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / LIBRARY / DSUTIL12 / BIN2FILE / BIN2FILE.PAS < prev   
Pascal/Delphi Source File  |  1993-10-28  |  17KB  |  534 lines

  1. {-----------------------------------------------------------------------}
  2. { PROJECT        NON-PROFIT HIGH QUALITY PROFESSIONAL SOFTWARE,  }
  3. {            AVAILABLE FOR ALL WORLD                }
  4. { LIBRARY        SYSTEM UTILITIES                                }
  5. { MODULE        BIN_TO_FILE_COPY                                }
  6. { FILE NAME        BIN2FILE.PAS                    }
  7. { PURPOSE        Put the binary partilal image to file           }
  8. { VERSION        1.30                        }
  9. { DATE            28-Oct-93                    }
  10. { DESIGN        Dmitry Stefankov                }
  11. { IMPLEMENTATION    Dmitry Stefankov                 }
  12. { COMPANY        Freelance Software Engineer            }
  13. { ADDRESS        Isakowskogo str, 4-2-30                }
  14. {            Moscow, 123181                    }
  15. {            USSR                        }
  16. {            Tel. 007 (095) 944-6304                }
  17. { COPYRIGHT NOTICE    Copyright (C) 1987-1993, Dmitry Stefankov    }
  18. { RESTRICTED RIGHTS    AVAILABLE ONLY FOR FREE DISTRIBUTION,           }
  19. {            NOT FOR COMMERCIAL PURPOSE            }
  20. { COMPUTER        IBM PC or compatible                }
  21. { OPERATING SYSTEM    MS/PC-DOS Version 3.30 or higher        }
  22. { COMPILER        Turbo Pascal Version 6.0            }
  23. {                       (Borland International Inc.) or compatible      }
  24. { ASSEMBLY LANGUAGE    Microsoft MASM 5.10 or compatible               }
  25. { LINKER        Turbo Pascal internal                           }
  26. { ARGUMENTS        <infile>     -  input  stream                   }
  27. {                       <outfile>    -  output stream                   }
  28. {                       <infilepos>  -  offset in input file            }
  29. {                       <outfilepos> -  offset in output file           }
  30. {                       <count>      -  # of bytes to copy              }
  31. { RETURN        None                        }
  32. { REQUIRES        None                                            }
  33. { NATURAL LANGUAGE      English Language                                 }
  34. { SPECIAL        None                        }
  35. { DESCRIPTION        1. Seek <infilepos>  for input file.            }
  36. {                       2. Seek <outfilepos> for output file.           }
  37. {                       2. Copy <count> bytes from input to output      }
  38. { REVISION HISTORY    Dima Stefankov (DS)                }
  39. {               1.00   08-Jan-92  DS  initilal release        }
  40. {                       1.01   09-Jan-92  DS  some syntax corrections   }
  41. {                       1.02   10-Jan-92  DS  new read/write algoritms  }
  42. {                       1.03   24-Jan-92  DS  some corrections          }
  43. {            1.10   25-Aug-92  DS  updated documentation    }
  44. {                       1.20   08-Oct-92  DS  some style corrections    }
  45. {                       1.21   27-Oct-92  DS  some corrections          }
  46. {                       1.22   04-Nov-92  DS  some updates              }
  47. {                       1.23   19-May-93  DS  some style updates        }
  48. {            1.24   04-Jul-93  DS  updated documentation    }
  49. {            1.30   28-Oct-93  DS  some style updates    }
  50. {-----------------------------------------------------------------------}
  51.  
  52.  
  53. {*======================= PROGRAM HEADER PART ==========================*}
  54.  
  55. PROGRAM   BinaryToBinaryCopy;
  56.  
  57.  
  58. {*** other modules ***}
  59. USES
  60.   Dos;
  61.  
  62.  
  63. {** switches for compilation **}
  64. {$S-}                {*  stack checking     *}
  65. {$R-}                   {*  range checking     *}
  66. {$M 16384,65536,65536}  {*  memory allocation  *}
  67.  
  68.  
  69. {*========================== CONSTANTS PART ============================*}
  70.  
  71. CONST
  72.  
  73.      asPurpose                  =       'Binary Image Copy';
  74.      asVersion                  =       '1.30';
  75.      asAuthor                   =       'Dima Stefankov';
  76.      asCopyright                =       'Copyright (c) 1987, 1993';
  77.      asProgram                  =       'Bin2file';
  78.      asProgramPrompt            =       asProgram+': ';
  79.      asProgramU                 =       'BIN2FILE';
  80.  
  81.      { exit codes }
  82.      errTerminateOK             =     0;
  83.      errBadParmsNumber          =     1;
  84.      errSourceNotFound          =     2;
  85.      errDestNotFound            =     3;
  86.      errBadInOffset             =     4;
  87.      errBadOutOffset            =     5;
  88.      errBadSize                 =     6;
  89.      errSrcOpenFailed           =     7;
  90.      errDestOpenFailed          =     8;
  91.      errSeekInSourceFailed      =     9;
  92.      errSeekInDestFailed        =     10;
  93.      errZeroLengthFound         =     11;
  94.      errBadInSize               =     12;
  95.      errSameNames               =     13;
  96.  
  97.      achHexPrefix               =     '$';
  98.      achDosExtMark              =     '.';
  99.      achCR                      =     #13;
  100.      asInDefExt                 =     'bin';
  101.      asOutDefExt                =     'exe';
  102.  
  103.      aHexRadix                  =     16;
  104.      aPercent100                =     100;
  105.      aMaxOnHeap                 =     65520;
  106.  
  107.  
  108. {*==================== TYPE DECLARATIONS PART ==========================*}
  109.  
  110. TYPE
  111.     STR3        =       STRING[3];
  112.  
  113.  
  114. {*====================== TYPED CONSTANTS PART ==========================*}
  115.  
  116. CONST
  117.     setHexChars          :    SET OF System.Char  =  ['0'..'9','A'..'F','a'..'f'];
  118.     gddBytesCountDone    :    System.Longint =  0;
  119.  
  120.  
  121. {*=========================== VARIABLES PART ===========================*}
  122.  
  123. VAR
  124.    gfInputStream    :   FILE;
  125.    gsInFileName     :   STRING[80];
  126.    gddOffsetInFile  :   System.Longint;
  127.  
  128.    gfOutputStream   :   FILE;
  129.    gsOutFileName    :   STRING[80];
  130.    gddOffsetOutFile :   System.Longint;
  131.    gddOutFileTime   :   System.Longint;
  132.  
  133.    gddByteCount     :   System.Longint;
  134.    gddInFileSize    :       System.Longint;
  135.  
  136.    gdwMemBlockSize  :   System.Word;
  137.    gdwBytesRead     :   System.Word;
  138.    gpMemoryBlock    :   System.Pointer;
  139.  
  140.    giErrorCode      :   System.Integer;
  141.  
  142.    gsTempInput      :   STRING;
  143.    gchInUser        :   System.Char;
  144.  
  145.  
  146. {*=========================== FUNCTIONAL PART ==========================*}
  147.  
  148. FUNCTION  _fndbHexCharToBin(chIn: System.Char) : System.Byte; assembler;
  149. {* Converts the hexadecimal char to decimal. *}
  150. asm
  151.         mov   al,chIn        { AL = chIn }
  152.         sub   al,'0'         { AL <- AL - '0' }
  153.  
  154.         cmp   al,9           { test for digit 0-9 }
  155.         jbe   @Done
  156.  
  157.         and   al,11011111b   { make uppercase }
  158.         sub   al,'A'-'9'-1   { AL = 'A'..'F' }
  159.  
  160.       @Done:
  161.                              { AL = function result }
  162. END;
  163.     {asm-end}
  164. { _fndbHexCharToBin }
  165.  
  166.  
  167. FUNCTION  _fnsForceFileNameExt(sFileName, sDefExt : STRING) : STRING;
  168. {* Add extension for filename if not present. *}
  169. BEGIN
  170.    IF (System.Pos(achDosExtMark,sFileName) = 0)
  171.      THEN sFileName := sFileName + achDosExtMark + sDefExt;
  172.    {if-then}
  173.   _fnsForceFileNameExt := sFileName;
  174. END;
  175. { _fnsForceFileNameExt }
  176.  
  177.  
  178. FUNCTION  _fnliHexStrToBin(sHexInput : STRING; VAR iErrCode : System.Integer) : System.Longint;
  179. {* Converts hexadecimal string to decimal number. *}
  180. VAR
  181.   ddNumber               :       System.Longint;
  182.   dbStrIndex, dbStrLen   :       System.Byte;
  183.  
  184. BEGIN
  185.   iErrCode   := 0;
  186.   ddNumber   := 0;
  187.   dbStrIndex := 1;
  188.   dbStrLen := System.Length(sHexInput);
  189.  
  190.   WHILE (iErrCode = 0) and (dbStrLen > 0) DO
  191.   BEGIN
  192.     IF  (sHexInput[dbStrIndex] IN setHexChars)
  193.     THEN  BEGIN
  194.                ddNumber := ddNumber * aHexRadix +
  195.                            _fndbHexCharToBin(sHexInput[dbStrIndex]);
  196.                System.Inc(dbStrIndex);
  197.                System.Dec(dbStrLen);
  198.           END
  199.     ELSE
  200.         iErrCode  := -1;
  201.     {if-then-else}
  202.   END;
  203.   {while-do}
  204.  
  205.   _fnliHexStrToBin := ddNumber;
  206. END;  { _fnliHexStrToBin }
  207.  
  208.  
  209. FUNCTION  _fnbFileExist(VAR fStruc : FILE; sFileName : STRING) : System.Boolean;
  210. {* Check that file exits. *}
  211. VAR
  212.   bResult  :  System.Boolean;
  213.  
  214. BEGIN
  215.   {** try to open the file **}
  216.   System.Assign(fStruc,sFileName);
  217.   {$I-}
  218.   System.Reset(fStruc);
  219.   {$I+}
  220.  
  221.   {** copy the result of last I/O operation **}
  222.   bResult := (System.IOResult = 0);
  223.  
  224.   IF (bResult)
  225.     THEN  System.Close(fStruc);
  226.   {if-then}
  227.  
  228.   _fnbFileExist := bResult;
  229. END; { _fnbFileExist }
  230.  
  231.  
  232. FUNCTION  _fnsUpcaseStr(sInput : STRING) : STRING;
  233. {* Make all uppercase. *}
  234. VAR
  235.   dbIndex  :  System.BYTE;
  236.   dbCount  :  System.BYTE;
  237.  
  238. BEGIN
  239.   dbCount := System.Length(sInput);
  240.  
  241.   IF (dbCount <> 0) THEN
  242.     FOR dbIndex :=  1  TO  dbCount DO
  243.       sInput[dbIndex] := System.Upcase(sInput[dbIndex]);
  244.     {for-to-do}
  245.   {if-then}
  246.  
  247.    _fnsUpcaseStr := sInput;
  248. END; { _fnsUpcaseStr }
  249.  
  250.  
  251. FUNCTION  _fnddGetNum(sInput : STRING;VAR iErrorCode : System.Integer)  :  System.Longint;
  252. {* Reads a numeric string. *}
  253. VAR
  254.   ddTemp      :   System.Longint;
  255.  
  256. BEGIN
  257.   IF  (sInput[1] <> achHexPrefix)
  258.      THEN  System.Val(sInput,ddTemp,iErrorCode)
  259.      ELSE  ddTemp := _fnliHexStrToBin(Copy(sInput,2,System.Length(sInput)-1),iErrorCode);
  260.   {if-then-else}
  261.   _fnddGetNum := ddTemp;
  262. END;
  263. { _fnddGetNum }
  264.  
  265.  
  266. FUNCTION  _fnsNumToStr3(dwNum : System.Word) : STR3;
  267. {* Convert a numeric value to its string representation. *}
  268. VAR
  269.   sTemp : STR3;
  270.  
  271. BEGIN
  272.    System.Str(dwNum:3,sTemp);
  273.    _fnsNumToStr3 := sTemp;
  274. END;
  275. { _fnsNumToStr3 }
  276.  
  277.  
  278.  
  279. {*=========================== PROCEDURAL PART ==========================*}
  280.  
  281. PROCEDURE    _CopyrightDisplay;
  282. {* Outputs the copyright notice. *}
  283. BEGIN
  284.      System.WriteLn(asPurpose+'  Version '+asVersion+',  '+asCopyright+'  '+asAuthor);
  285. END;  { _CopyrightDisplay }
  286.  
  287.  
  288.  
  289. {*============================== MAIN PART =============================*}
  290.  
  291. BEGIN
  292.   _CopyrightDisplay;
  293.  
  294.      IF (System.ParamCount <> 5) THEN
  295.      BEGIN
  296.           System.WriteLn(asProgramPrompt+'  help screen for you.');
  297.           System.WriteLn('Usage: infile outfile inoffset outoffset size');
  298.           System.WriteLn('  infile     -  source filename      (def. ext. = '+asInDefExt+')');
  299.           System.WriteLn('  outfile    -  destination filename (def. ext. = '+asOutDefExt+')');
  300.           System.WriteLn('  inoffset   -  offset in source');
  301.           System.WriteLn('  outoffset  -  offset in destination');
  302.           System.WriteLn('  size       -  number of bytes to transfer');
  303.           System.WriteLn('  Numbers may be decimals, or hexadecimals (first symbol is ''$'' for hex.).');
  304.           System.Halt(errBadParmsNumber);
  305.      END;
  306.      {if-then}
  307.  
  308.  
  309.   {** copy the parameters from command line **}
  310.   gsInFileName  := _fnsUpcaseStr(System.ParamStr(1));
  311.   gsInFileName := _fnsForceFileNameExt(gsInFileName,asInDefExt);
  312.  
  313.   gsOutFileName := _fnsUpcaseStr(System.ParamStr(2));
  314.   gsOutFileName := _fnsForceFileNameExt(gsOutFileName,asOutDefExt);
  315.  
  316.  
  317.   {* may be same names? *}
  318.   IF (gsInFileName = gsOutFileName)  THEN
  319.   BEGIN
  320.     System.WriteLn(asProgramPrompt+'  Unable to use same file as input and as output');
  321.     System.Halt(errSameNames);
  322.   END;
  323.   {if-then}
  324.  
  325.  
  326.   {** source file exists? **}
  327.   IF  NOT(_fnbFileExist(gfInputStream,gsInFileName)) THEN
  328.   BEGIN
  329.     System.WriteLn(asProgramPrompt+' Unable to open file '+gsInFileName);
  330.     System.Halt(errSourceNotFound);
  331.   END;
  332.   {if-then}
  333.  
  334.  
  335.   {** destination file exists? **}
  336.   IF  NOT(_fnbFileExist(gfOutputStream,gsOutFileName)) THEN
  337.   BEGIN
  338.     System.WriteLn(asProgramPrompt+' Unable to open file '+gsOutFileName);
  339.     System.Halt(errDestNotFound);
  340.   END;
  341.   {if-then}
  342.  
  343.  
  344.   {** read the following parameter = offset for source **}
  345.   gsTempInput := System.ParamStr(3);
  346.   gddOffsetInFile := _fnddGetNum(gsTempInput,giErrorCode);
  347.  
  348.   IF  (giErrorCode <> 0)  THEN
  349.       BEGIN
  350.         System.WriteLn(asProgramPrompt+' Bad offset parameter for source.');
  351.         System.Halt(errBadInOffset);
  352.       END;
  353.    {if-then}
  354.  
  355.  
  356.   {** read the following parameter = offset for dest **}
  357.   gsTempInput := System.ParamStr(4);
  358.   gddOffsetOutFile := _fnddGetNum(gsTempInput,giErrorCode);
  359.  
  360.   IF  (giErrorCode <> 0)  THEN
  361.       BEGIN
  362.         System.WriteLn(asProgramPrompt+' Bad offset parameter for target.');
  363.         System.Halt(errBadOutOffset);
  364.       END;
  365.   {if-then}
  366.  
  367.  
  368.   {** read the following parameter = size **}
  369.   gsTempInput  := System.ParamStr(5);
  370.   gddByteCount := _fnddGetNum(gsTempInput,giErrorCode);
  371.  
  372.   IF  (giErrorCode <> 0)  THEN
  373.       BEGIN
  374.         System.WriteLn(asProgramPrompt+' Bad size parameter.');
  375.         System.Halt(errBadSize);
  376.       END;
  377.   {if-then}
  378.  
  379.     gddInFileSize := gddByteCount;
  380.  
  381.  
  382.   {** open the source file **}
  383.   System.Assign(gfInputStream,gsInFileName);
  384.   {$I-}
  385.   System.Reset(gfInputStream,1);
  386.   {$I+}
  387.  
  388.   IF  (System.IoResult <> 0) THEN
  389.   BEGIN
  390.     System.WriteLn(asProgramPrompt+' Unable to open '+gsInFileName);
  391.     System.Halt(errSrcOpenFailed);
  392.   END;
  393.   {if-then}
  394.  
  395.   {** open the destination file **}
  396.   System.Assign(gfOutputStream,gsOutFileName);
  397.   {$I-}
  398.   System.Reset(gfOutputStream,1);
  399.   {$I+}
  400.  
  401.   IF  (System.IoResult <> 0) THEN
  402.   BEGIN
  403.     System.Close(gfInputStream);
  404.     System.WriteLn(asProgramPrompt+' Unable to open '+gsOutFileName);
  405.     System.Halt(errDestOpenFailed);
  406.   END;
  407.   {if-then}
  408.  
  409.  
  410.  
  411.   {** find the wanted # of bytes **}
  412.   IF  (System.FileSize(gfInputStream) < gddByteCount) THEN
  413.     BEGIN
  414.         System.Close(gfInputStream);
  415.         System.Close(gfOutputStream);
  416.         System.WriteLn(asProgramPrompt+' more bytes requested than in source file.');
  417.         System.Halt(errBadInSize);
  418.     END;
  419.   {if-then}
  420.  
  421.  
  422.   {** recalculate # of bytes to copy **}
  423.   IF  (System.FileSize(gfInputStream) < (gddOffsetInFile + gddByteCount))
  424.     THEN  BEGIN
  425.       gddByteCount := System.FileSize(gfInputStream) - gddOffsetInFile;
  426.       System.WriteLn(asProgramPrompt+' Warning! Only partial copy...');
  427.           END;
  428.   {if-then}
  429.  
  430.   IF  (System.FileSize(gfOutputStream) < (gddOffsetOutFile + gddByteCount))
  431.     THEN  BEGIN
  432.       gddByteCount := System.FileSize(gfOutputStream) - gddOffsetOutFile;
  433.       System.WriteLn(asProgramPrompt+' Warning! Only partial copy...');
  434.           END;
  435.   {if-then}
  436.  
  437.  
  438.   IF  (gddByteCount = 0) THEN
  439.   BEGIN
  440.     System.Close(gfInputStream);
  441.     System.Close(gfOutputStream);
  442.     System.WriteLn(asProgramPrompt+' Zero found for bytes count.');
  443.     System.Halt(errZeroLengthFound);
  444.   END;
  445.   {if-then}
  446.  
  447.  
  448.   {** seek wanted position in input file **}
  449.   IF  (System.FileSize(gfInputStream) <= gddOffsetInFile) THEN
  450.   BEGIN
  451.     System.Close(gfInputStream);
  452.     System.Close(gfOutputStream);
  453.     System.WriteLn(asProgramPrompt+' Seek operation in source file failed.');
  454.     System.Halt(errSeekInSourceFailed);
  455.   END;
  456.   {if-then}
  457.  
  458.   {$I-}
  459.   System.Seek(gfInputStream,gddOffsetInFile);
  460.   {$I+}
  461.  
  462.  
  463.   {** seek wanted position in input file. **}
  464.   IF  (System.FileSize(gfOutputStream) <= gddOffsetOutFile) THEN
  465.   BEGIN
  466.     System.Close(gfInputStream);
  467.     System.Close(gfOutputStream);
  468.     System.WriteLn(asProgramPrompt+' Seek operation in target file failed.');
  469.     System.Halt(errSeekInDestFailed);
  470.   END;
  471.   {if-then}
  472.  
  473.   {$I-}
  474.   System.Seek(gfOutputStream,gddOffsetOutFile);
  475.   {$I+}
  476.  
  477.  
  478.  
  479.   {** get memory on heap **}
  480.   IF  (System.MaxAvail < aMaxOnHeap)
  481.     THEN  gdwMemBlockSize := System.MaxAvail
  482.     ELSE  gdwMemBlockSize := aMaxOnHeap;
  483.   {if-then-else}
  484.   System.GetMem(gpMemoryBlock,gdwMemBlockSize);
  485.  
  486.  
  487.   {* get date/time for output file *}
  488.   Dos.GetFTime(gfOutputStream,gddOutFileTime);
  489.  
  490.  
  491.   {** simple algorithm to buffered copy **}
  492.   WHILE (gddByteCount <> 0) DO
  493.   BEGIN
  494.       IF  ((gddByteCount DIV gdwMemBlockSize) <> 0)
  495.         THEN  gdwBytesRead := gdwMemBlockSize
  496.         ELSE  gdwBytesRead := gddByteCount;
  497.       {if-then-else}
  498.  
  499.                System.WriteLn(asProgramPrompt+' Reading...');
  500.                System.BlockRead(gfInputStream,
  501.                                 System.Mem[System.Seg(gpMemoryBlock^):System.Ofs(gpMemoryBlock^)],
  502.                                 gdwBytesRead,
  503.                                 gdwBytesRead);
  504.                System.WriteLn(asProgramPrompt+' Writing...');
  505.                System.BlockWrite(gfOutputStream,
  506.                                  System.Mem[System.Seg(gpMemoryBlock^):System.Ofs(gpMemoryBlock^)],
  507.                                  gdwBytesRead);
  508.                System.Dec(gddByteCount,gdwBytesRead);
  509.                System.Write(achCR+asProgramPrompt+' Completed ('+
  510.                _fnsNumToStr3((gddBytesCountDone*aPercent100) DIV gddInFileSize)+'%)');
  511.                System.WriteLn;
  512.   END;
  513.   {while-do}
  514.  
  515.  
  516.   {** free memory on heap **}
  517.   System.FreeMem(gpMemoryBlock,gdwMemBlockSize);
  518.  
  519.  
  520.   {* restore old date/time for output file *}
  521.   Dos.SetFTime(gfOutputStream,gddOutFileTime);
  522.  
  523.   {** close all files **}
  524.   System.Close(gfInputStream);
  525.   System.Close(gfOutputStream);
  526.  
  527.  
  528.   {** report all done **}
  529.   System.WriteLn(asProgramPrompt+' Done.');
  530.  
  531.   {* System.Halt(errTerminateOk); *}
  532. END.
  533.  
  534.